package net.betou.trade.action;

import static net.betou.core.manager.AuthenticationMng.AUTH_KEY;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.betou.common.security.exception.BadCredentialsException;
import net.betou.common.security.exception.DisabledException;
import net.betou.common.security.exception.UsernameNotFoundException;
import net.betou.common.web.RequestUtils;
import net.betou.common.web.session.SessionProvider;
import net.betou.core.entity.Authentication;
import net.betou.core.manager.AuthenticationMng;
import net.betou.trade.entity.main.AgentAndAdmins;
import net.betou.trade.main.manager.LogMng;
import net.betou.trade.main.manager.agencyorproxy.AdminMng;
import net.betou.trade.web.Messages;
import net.betou.trade.web.WebErrors;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.octo.captcha.service.CaptchaServiceException;
import com.octo.captcha.service.image.ImageCaptchaService;

/**
 * 
 * @author 叶装装
 * 
 *         实现三种方式登录： 用户名， 手机， email 如果是手机： 11位，并且全是数字， email 格式, 用户名,
 *         目前实现方式只根据用户名来实现
 */
@Controller
public class TradeLoginAct{

	public static final String ADMIN_KEY = "_admin_key";
	public static final String PROCESS_URL = "processUrl";
	public static final String RETURN_URL = "returnUrl";

	/**
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 */
	@RequestMapping( value = "/login.jspx", method = RequestMethod.GET )
	public String input( HttpServletRequest request, HttpServletResponse response, ModelMap model ) {
		String processUrl = RequestUtils.getQueryParam( request, PROCESS_URL );
		String returnUrl = RequestUtils.getQueryParam( request, RETURN_URL );
		String authId = ( String ) session.getAttribute( request, AUTH_KEY );

		if( authId != null ){
			// 存在认证ID
			Authentication auth = authMng.retrieve( authId );
			// 存在认证信息，且未过期
			if( auth != null ){
				String view = getView( processUrl, returnUrl, auth.getId( ) );
				if( view != null ){
					return view;
				}else{
					model.addAttribute( "auth", auth );
					return "redirect:index.jspx";
				}
			}
		}
	
		if( !StringUtils.isBlank( processUrl ) ){
			model.addAttribute( PROCESS_URL, processUrl );
		}
		if( !StringUtils.isBlank( returnUrl ) ){
			model.addAttribute( RETURN_URL, returnUrl );
		}

		return "login";
	}

	@RequestMapping( value = "/login.jspx", method = RequestMethod.POST )
	public String submit( String username, String password, String captcha, String processUrl, String returnUrl, String message, HttpServletRequest request, HttpServletResponse response, ModelMap model ) {
		
		WebErrors errors = validateSubmit( username, password, captcha, request, response );
		
		if( !errors.hasErrors( ) ){
			try{
				String ip = RequestUtils.getIpAddr( request );
				Authentication auth = authMng.login( username, password, ip, request, response, session );
				
				AgentAndAdmins user = adminMng.findById( auth.getUid( ) );
			
				if( user.getDisabled( ) ){
					// 如果已经禁用，则退出登录。
					authMng.deleteById( auth.getId( ) );
					session.logout( request, response );
					throw new DisabledException( "user disabled" );
				}
				
				String view = getView( processUrl, returnUrl, auth.getId( ) );
				logMng.loginSuccess( request, user, Messages.LOG_LOGIN_SUCCESS );
				
				if( view != null ){
					return view;
				}else{
					return "redirect:login.jspx";
				}
			}catch( UsernameNotFoundException e ){
				errors.addError( Messages.LOGIN_ERROR );
				logMng.loginFailure( request, Messages.LOG_LOGIN_ERROR, "username=" + username + ";password=" + password );
			}catch( BadCredentialsException e ){
				errors.addError( Messages.LOGIN_ERROR);
				logMng.loginFailure( request, Messages.LOG_LOGIN_ERROR, "username=" + username + ";password=" + password );
			}catch( DisabledException e ){
				errors.addError( Messages.USER_DISABLED );
				logMng.loginFailure( request, Messages.LOG_LOGIN_ERROR, "username=" + username + ";password=" + password );
			}
		}
		
		errors.toModel( model );
		model.addAttribute( "username", username );
		
		if( !StringUtils.isBlank( processUrl ) ){
			model.addAttribute( PROCESS_URL, processUrl );
		}
		if( !StringUtils.isBlank( returnUrl ) ){
			model.addAttribute( RETURN_URL, returnUrl );
		}
		
		return "login";
	}

	@RequestMapping( value = "/logout.jspx" )
	public String logout( HttpServletRequest request, HttpServletResponse response ) {
		String authId = ( String ) session.getAttribute( request, AUTH_KEY );
		if( authId != null ){
			authMng.deleteById( authId );
			session.logout( request, response );
		}
		String processUrl = RequestUtils.getQueryParam( request, PROCESS_URL );
		String returnUrl = RequestUtils.getQueryParam( request, RETURN_URL );
		String view = getView( processUrl, returnUrl, authId );
		if( view != null ){
			return view;
		}else{
			return "redirect:login.jspx";
		}
	}
	
	private WebErrors validateSubmit( String username, String password, String captcha, HttpServletRequest request, HttpServletResponse response ) {
		WebErrors errors = WebErrors.create(  );
		
		if( errors.ifOutOfLength( username, "username", 1, 100 ) ){
			return errors;
		}
		if( errors.ifOutOfLength( password, "password", 1, 2000 ) ){
			return errors;
		}
		
		try{
			if( !imageCaptchaService.validateResponseForID( session.getSessionId( request, response ), captcha ) ){
				errors.addError( Messages.LOGIN_CAPTCHA_ERROR );
				return errors;
			}
		}catch( CaptchaServiceException e ){
			errors.addError( Messages.LOGIN_CAPTCHA_INVALID );
			
			return errors;
		}
		
		return errors;
	}

	/**
	 * 获得地址
	 * 
	 * @param processUrl
	 * @param returnUrl
	 * @param authId
	 * @param defaultUrl
	 * @return
	 */
	private String getView( String processUrl, String returnUrl, String authId ) {
		if( !StringUtils.isBlank( processUrl ) ){
			StringBuilder sb = new StringBuilder( "redirect:" );
			sb.append( processUrl ).append( "?" ).append( AUTH_KEY ).append( "=" ).append( authId );
			if( !StringUtils.isBlank( returnUrl ) ){
				sb.append( "&" ).append( RETURN_URL ).append( "=" ).append( returnUrl );
			}
			return sb.toString( );
		}else if( !StringUtils.isBlank( returnUrl ) ){
			StringBuilder sb = new StringBuilder( "redirect:" );
			sb.append( returnUrl );
			return sb.toString( );
		}else{
			return null;
		}
	}

	@Autowired
	private SessionProvider session;
	@Autowired
	private ImageCaptchaService imageCaptchaService;
	
	@Autowired
	private AdminMng adminMng;

	@Autowired
	private AuthenticationMng authMng;
	
	@Autowired
	private LogMng logMng;
}
